package com.twl.app.base.bo;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;

import javax.annotation.PostConstruct;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.twl.app.base.entity.SalDesKey;
import com.twl.app.base.task.DesKeyGenerator;
import com.twl.app.base.util.ThreeDESUtils;
import com.twl.common.constant.SalConstant;
import com.twl.core.framework.dao.WSHibernateDaoSupportProxy;

@Component
public class CryptService implements Observer {
	
	private static Logger log = Logger.getLogger(CryptService.class);
	
	private  final static ReentrantReadWriteLock LOCK =new ReentrantReadWriteLock();
	//read
	private final static ReadLock READ_LOCK = LOCK.readLock();
	//write
	private final static WriteLock WRITE_LOCK = LOCK.writeLock();

	@Autowired
	private WSHibernateDaoSupportProxy wsHibernateDaoSupportProxy;

	@Autowired
	private DesKeyGenerator desKeyGenerator;
	
	/**
	 * 存放3DES完整密钥
	 */
	private volatile static Map<String, String> DES_KEY_MAP = new ConcurrentHashMap<String, String>();

	@PostConstruct
	public void init(){
		try {
			this.initDesKeyMap();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	private void initDesKeyMap() throws Exception {
		try{
			WRITE_LOCK.lock();
			log.info("初始化密钥Map...");
			// 清除
			DES_KEY_MAP.clear();

			String listHql = " from SalDesKey t where t.desEffective='" + SalConstant.TRUE + "' and t.isDelete='" + SalConstant.NOT_DELETE + "' ";

			String hql = " from SalDesKey t where t.desEffective='" + SalConstant.TRUE + "' and t.isDelete='" + SalConstant.NOT_DELETE + "' and t.id = (select max(id) from SalDesKey s where s.desEffective='" + SalConstant.TRUE + "' and s.isDelete='" + SalConstant.NOT_DELETE + "' ) ";

			@SuppressWarnings("unchecked")
			List<SalDesKey> list = wsHibernateDaoSupportProxy.list(listHql);

			if (list != null && !list.isEmpty()) {

				SalDesKey lastKey = (SalDesKey) wsHibernateDaoSupportProxy.uniqueResult(hql);
				// 最新一条密钥
				DES_KEY_MAP.put(SalConstant.LAST_KEY_ID, ThreeDESUtils.encryptThreeDESECB(lastKey.getId().toString(), ThreeDESUtils.DES_ID_KEY));
				DES_KEY_MAP.put(SalConstant.LAST_KEY, ThreeDESUtils.HALF_KEY + lastKey.getDesKey());
				log.info("已获取最新密钥...");
				for (SalDesKey key : list) {
					// 密钥主键加密/密钥
					DES_KEY_MAP.put(ThreeDESUtils.encryptThreeDESECB(key.getId().toString(), ThreeDESUtils.DES_ID_KEY), ThreeDESUtils.HALF_KEY + key.getDesKey());
				}
				log.info("已获取历史密钥...");
				log.info("初始化密钥Map完成...");
			} else {
				log.info("数据库中不存在密钥,初始化密钥Map失败...");
			}
			
//			Set<Entry<String,String>> set = DES_KEY_MAP.entrySet();
//			Iterator<Entry<String,String>> iterator = set.iterator();
//			while(iterator.hasNext()){
//				Entry<String,String> entry = iterator.next();
//				log.info(entry.getKey()+"  "+entry.getValue());
//			}
			
		}catch(Exception e){
			e.printStackTrace();
		}finally {
			WRITE_LOCK.unlock();
		}
	}
	
	public static String getValueByKey(String key) {
		String value = null;
		try {
			READ_LOCK.lock();
			value = DES_KEY_MAP.get(key);
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			READ_LOCK.unlock();
		}
		return value;
	}
	
	/**
	 * 获取所有密钥
	 * @return
	 */
	public static List<String> getDesKeyList(){
		List<String> list = new ArrayList<String>();
		try {
			READ_LOCK.lock();
			Set<Entry<String,String>> set =   DES_KEY_MAP.entrySet();
			Iterator<Entry<String,String>> iterator = set.iterator();
			while(iterator.hasNext()){
				Entry<String,String> entry = iterator.next();
				if(!SalConstant.LAST_KEY.equals(entry.getKey())&&!SalConstant.LAST_KEY_ID.equals(entry.getKey())){
					list.add(entry.getValue());
				}
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			READ_LOCK.unlock();
		}
		return list;
	}
	
	

	/**
	 * 通过观察着模式更新DES_KEY_MAP
	 */
	@Override
	public void update(Observable o, Object arg) {
		try {
			log.info(o.getClass()+" 添加了新的密钥...");
			this.initDesKeyMap();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@PostConstruct
	public void addObserver() {
		desKeyGenerator.addObserver(this);
	}

	
}
